package com.qf.controller;

import com.qf.utils.ZkConfig;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.recipes.locks.InterProcessMutex;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 模拟 秒杀商品
 * @author lixu
 */
@SuppressWarnings("all") //不要报错 ： 关于重复性代码
@RestController
@RequestMapping("/seckill")
public class SecondKillController {

    //集合 充当 Mysql数据库
    private static Map<String,Integer> itemNum = new HashMap<>();
    private static Map<String,Integer> orderNum = new HashMap<>();

    private final Lock lock1 = new ReentrantLock(true);//公平锁  等待时间最长的获取锁
    private final Lock lock2 = new ReentrantLock(false);//不公平锁

    static {
        //初始化商品的数据
        itemNum.put("牙刷",10000);
        //订单的数据
        orderNum.put("牙刷",0);
    }

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * Redis   setnx   如果锁已经存在了 就不能获取锁了  如果锁不存在就获取锁
     *
     *
     *                 如果key值 已经存在了就不设置了  如果不存在就设置
     */
    @GetMapping("/submitOrder3")
    public String submitOrder3(String name){
        //加锁  过期不候的锁
        //redisTemplate.opsForValue().setIfAbsent("lock","gp14",5, TimeUnit.SECONDS);
        // 不见不散的锁
        Boolean isHaveLock = false;
        do {
            isHaveLock = redisTemplate.opsForValue().setIfAbsent("lock", "gp14", 5, TimeUnit.SECONDS);
        } while(!isHaveLock);

        try {
            //1:判断商品库存是否还有
            Integer num = itemNum.get(name);
            if(num <= 0){
                //无货 无库存
                return "无货";
            }else{
                num--;
                itemNum.put(name,num);
                //生成订单
                Integer oNum = orderNum.get(name);
                orderNum.put(name,oNum+1);
            }
        } finally {
            //解锁
            redisTemplate.delete("lock");
        }
        //3. 返回信息
        return "抢购成功！！！"
                + name + "： 剩余库存数为 - "
                + itemNum.get(name) + "，订单数为 - "
                + orderNum.get(name);

    }











    /**
     *       //1:查询Mysql数据库中商品的数量  判断是否还有商品可以售卖
     *         //2:生成订单表
     * 下订单
     */
    @GetMapping("/submitOrder")
    public String submitOrder1(String name){

//        加锁
        lock2.lock();//不见不散  本地锁：没有过期时间  没有解锁 就是死锁
        try {
            //1:判断商品库存是否还有
            Integer num = itemNum.get(name);
            if(num <= 0){
               //无货 无库存
                return "无货";
            }else{
                num--;
                itemNum.put(name,num);
                //生成订单
                Integer oNum = orderNum.get(name);
                orderNum.put(name,oNum+1);
            }
        } finally {
            //解锁
            lock2.unlock();
        }
        //3. 返回信息
        return "抢购成功！！！"
                + name + "： 剩余库存数为 - "
                + itemNum.get(name) + "，订单数为 - "
                + orderNum.get(name);

    }


    @Autowired
    private CuratorFramework cf;

    /**
     *       //1:查询Mysql数据库中商品的数量  判断是否还有商品可以售卖
     *         //2:生成订单表
     * 下订单
     */
    @GetMapping("/submitOrder2")
    public String submitOrder2(String name) throws Exception{
        //
        InterProcessMutex ipm = new InterProcessMutex(cf,"/lock");// lock0000001 lock0000002 ...

        ipm.acquire();//不见不散的锁  死锁   阻塞
        try {
            //1:判断商品库存是否还有
            Integer num = itemNum.get(name);
            if(num <= 0){
                //无货 无库存
                return "无货";
            }else{
                num--;
                itemNum.put(name,num);
                //生成订单
                Integer oNum = orderNum.get(name);
                orderNum.put(name,oNum+1);
            }
        } finally {
            //解锁
            ipm.release();//释放锁
        }
        //3. 返回信息
        return "抢购成功！！！"
                + name + "： 剩余库存数为 - "
                + itemNum.get(name) + "，订单数为 - "
                + orderNum.get(name);

    }
}
